package com.fitness.front.utils;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;
import org.springframework.util.StringUtils;

import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;

/**
 * @author DUHAOLIN
 * @date 2024/12/2
 */
public class HttpUtils {

    private static final String JSON_FORMAT = "application/json";
    private static final String UTF8_CHARSET = "utf-8";
    private static final RequestConfig DEFAULT_REQUEST_CONFIG = HttpClient.getInstance().getDefaultRequestConfig();


    public static HttpEntity doGet(String url) {
        return send(url, HttpClient.getInstance());
    }

    private static HttpEntity send(String url, HttpClient httpClient) {
        HttpGet get = new HttpGet(url);

        try {
            get.setConfig(DEFAULT_REQUEST_CONFIG);
            HttpResponse response = httpClient.getHttpClient().execute(get);
            return response.getEntity();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static String doHttpPost(String url) {
        return sendData(url, createSSLInsecureClient(), UTF8_CHARSET);
    }

    public static String doHttpPost(String url, String data) {
        return sendData(url, data, createSSLInsecureClient(), UTF8_CHARSET);
    }

    public static String doHttpPost(String url, String data, String encoding) {
        return sendData(url, data, createSSLInsecureClient(), encoding);
    }

    public static String doHttpPost(String url, String data, String encoding, String contentType) {
        return sendData(url, data, createSSLInsecureClient(), encoding, contentType);
    }

    public static String doHttpsPost(String data, String url, String certAddress, String mchId, String TLSVersion, String encoding) {
        return sendData(url, data, getCAHttpClient(mchId, certAddress, TLSVersion), encoding);
    }

    private static String sendData(String url, String data, CloseableHttpClient httpClient, String encoding) {
        return sendData(url, data, httpClient, encoding, JSON_FORMAT);
    }

    private static CloseableHttpClient getCAHttpClient(String mchId, String certAddress, String TLSVersion) {
        if (!StringUtils.hasText(TLSVersion)) {
            TLSVersion = "TLSv1";
        }
        CloseableHttpClient httpClient = null;
        try {
            KeyStore keyStore = KeyStore.getInstance("PKCS12");
            try (FileInputStream inputStream = new FileInputStream(certAddress)) {
                keyStore.load(inputStream, mchId.toCharArray());
            }
            SSLContext context = SSLContexts.custom()
                    .loadKeyMaterial(keyStore, mchId.toCharArray())
                    .build();
            SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(
                    context,
                    new String[] { TLSVersion },
                    null,
                    SSLConnectionSocketFactory.getDefaultHostnameVerifier()
            );
            httpClient = HttpClients.custom()
                    .setSSLSocketFactory(factory)
                    .build();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return httpClient;
    }

    private static String sendData(String url, String data, CloseableHttpClient httpClient, String encoding, String contentType) {
        HttpPost post = new HttpPost(url);
        String result = null;
        try {
            post.setConfig(DEFAULT_REQUEST_CONFIG);
            StringEntity entity = new StringEntity(data, UTF8_CHARSET);
            entity.setContentEncoding(UTF8_CHARSET);
            entity.setContentType(contentType);
            post.setEntity(entity);
            HttpResponse response = httpClient.execute(post);
            HttpEntity returnEntity = response.getEntity();
            result = EntityUtils.toString(returnEntity, encoding);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    private static CloseableHttpClient createSSLInsecureClient() {
        try {
            SSLContext context = new SSLContextBuilder()
                    .loadTrustMaterial(null, (x509Certificates, s) -> true)
                    .build();
            SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(context, new NoopHostnameVerifier());
            return HttpClients.custom()
                    .setSSLSocketFactory(factory)
                    .build();
        } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {
            e.printStackTrace();
        }
        return HttpClients.createDefault();
    }

    private static String sendData(String url, CloseableHttpClient httpClient, String encoding) {
        HttpPost post = new HttpPost(url);
        String result;
        try {
            post.setConfig(DEFAULT_REQUEST_CONFIG);
            HttpResponse response = httpClient.execute(post);
            HttpEntity entity = response.getEntity();
            result = EntityUtils.toString(entity, encoding);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("请求异常", e);
        }
        return result;
    }

}
